/*
    Mango - Open Source M2M - http://mango.serotoninsoftware.com
    Copyright (C) 2006-2011 Serotonin Software Technologies Inc.
    @author Matthew Lohbihler
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.serotonin.mango.web.mvc.controller;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ParameterizableViewController;

import com.serotonin.ShouldNeverHappenException;
import com.serotonin.mango.Common;
import com.serotonin.mango.db.dao.DataPointDao;
import com.serotonin.mango.db.dao.EventDao;
import com.serotonin.mango.db.dao.UserDao;
import com.serotonin.mango.db.dao.ViewDao;
import com.serotonin.mango.view.View;
import com.serotonin.mango.view.chart.ImageChartRenderer;
import com.serotonin.mango.view.chart.ImageFlipbookRenderer;
import com.serotonin.mango.view.chart.TableChartRenderer;
import com.serotonin.mango.vo.DataPointVO;
import com.serotonin.mango.vo.User;
import com.serotonin.mango.vo.permission.Permissions;
import com.serotonin.util.StringUtils;

public class DataPointDetailsController extends ParameterizableViewController {
    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Map<String, Object> model = new HashMap<String, Object>();
        User user = Common.getUser(request);

        int id;
        DataPointDao dataPointDao = new DataPointDao();
        String idStr = request.getParameter("dpid");
        if (StringUtils.isEmpty(idStr)) {
            // Check for pedid (point event detector id)
            String pedStr = request.getParameter("pedid");
            if (pedStr == null)
                throw new ShouldNeverHappenException("dpid or pedid must be provided for this view");

            int pedid = Integer.parseInt(pedStr);
            id = dataPointDao.getDataPointIdFromDetectorId(pedid);
        }
        else
            id = Integer.parseInt(idStr);

        // Put the point in the model.
        DataPointVO point = dataPointDao.getDataPoint(id);

        Permissions.ensureDataPointReadPermission(user, point);

        model.put("point", point);

        // Get the views for this user that contain this point.
        List<View> userViews = new ViewDao().getViews(user.getId());
        List<View> views = new LinkedList<View>();
        for (View view : userViews) {
            view.validateViewComponents(false);
            if (view.containsValidVisibleDataPoint(id))
                views.add(view);
        }
        model.put("views", views);

        // Get the users that have access to this point.
        List<User> allUsers = new UserDao().getUsers();
        List<Map<String, Object>> users = new LinkedList<Map<String, Object>>();
        Map<String, Object> userData;
        int accessType;
        for (User mangoUser : allUsers) {
            accessType = Permissions.getDataPointAccessType(mangoUser, point);
            if (accessType != Permissions.DataPointAccessTypes.NONE) {
                userData = new HashMap<String, Object>();
                userData.put("user", mangoUser);
                userData.put("accessType", accessType);
                users.add(userData);
            }
        }
        model.put("users", users);

        // Determine whether the link to edit the point should be displayed
        model.put("pointEditor", Permissions.hasDataSourcePermission(user, point.getDataSourceId()));

        // Put the events in the model.
        model.put("events", new EventDao().getEventsForDataPoint(id, user.getId()));

        // Put the default history table count into the model. Default to 10.
        int historyLimit = 10;
        if (point.getChartRenderer() instanceof TableChartRenderer)
            historyLimit = ((TableChartRenderer) point.getChartRenderer()).getLimit();
        else if (point.getChartRenderer() instanceof ImageFlipbookRenderer)
            historyLimit = ((ImageFlipbookRenderer) point.getChartRenderer()).getLimit();
        model.put("historyLimit", historyLimit);

        // Determine our image chart rendering capabilities.
        if (ImageChartRenderer.getDefinition().supports(point.getPointLocator().getDataTypeId())) {
            // This point can render an image chart. Carry on...
            int periodType = Common.TimePeriods.DAYS;
            int periodCount = 1;
            if (point.getChartRenderer() instanceof ImageChartRenderer) {
                ImageChartRenderer r = (ImageChartRenderer) point.getChartRenderer();
                periodType = r.getTimePeriod();
                periodCount = r.getNumberOfPeriods();
            }
            model.put("periodType", periodType);
            model.put("periodCount", periodCount);
        }

        // Determine out flipbook rendering capabilities
        if (ImageFlipbookRenderer.getDefinition().supports(point.getPointLocator().getDataTypeId()))
            model.put("flipbookLimit", 10);

        // Set the point in the session for the dwr.
        user.setEditPoint(point);

        // Find accessible points for the goto list
        ControllerUtils.addPointListDataToModel(user, id, model);

        return new ModelAndView(getViewName(), model);
    }
}
